package com.jzxiang.pickerview.wheel;

import ohos.agp.components.AttrHelper;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.components.DirectionalLayout;
import ohos.agp.components.LayoutScatter;
import ohos.agp.components.Picker;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.utils.Color;
import ohos.app.Context;

import com.jzxiang.pickerview.ResourceTable;
import com.jzxiang.pickerview.adapters.WheelViewAdapter;
import com.jzxiang.pickerview.config.DefaultConfig;
import com.jzxiang.pickerview.config.PickerConfig;

import java.util.LinkedList;
import java.util.List;


/**
 * 继承Component 是为了屏蔽外界 Picker 的调用
 *
 * @since 2021-07-19
 */
public class WheelView extends DirectionalLayout implements Component.DrawTask, Component.EstimateSizeListener {
    private int itemHeight = 79;

    private int width;
    private int height;
    private int mLineRightMar;

    private WheelViewAdapter mAdapter;
    private Picker mPicker;

    private Paint mCenterRectPaint;
    private Paint mLineRectPaint;
    private Paint mPaintLineRight;
    boolean isCyclic = false;

    private List<OnWheelChangedListener> changingListeners = new LinkedList<>();

    /**
     * WheelView
     *
     * @param context context
     */
    public WheelView(Context context) {
        super(context);
        init(context);
    }

    /**
     * WheelView
     *
     * @param context context
     * @param attrSet attrSet
     */
    public WheelView(Context context, AttrSet attrSet) {
        super(context, attrSet);
        init(context);
    }

    /**
     * WheelView
     *
     * @param context context
     * @param attrSet attrSet
     * @param styleName styleName
     */
    public WheelView(Context context, AttrSet attrSet, String styleName) {
        super(context, attrSet, styleName);
        init(context);
    }

    private void init(Context context) {
        setEstimateSizeListener(this);
        addDrawTask(this, DrawTask.BETWEEN_BACKGROUND_AND_CONTENT);
        Component rootView = LayoutScatter.getInstance(context).parse(ResourceTable.Layout_timepicker_layout2, this, true);
        mPicker = (Picker) rootView.findComponentById(ResourceTable.Id_pick);
        mPicker.setFormatter(new DataFormat());
        mPicker.setValueChangedListener(new ValueChange());
        mPicker.setNormalTextColor(new Color(DefaultConfig.TV_NORMAL_COLOR));
        mPicker.setSelectedTextColor(new Color(DefaultConfig.TV_SELECTOR_COLOR));
        mPicker.setSelectedTextSize(AttrHelper.fp2px(DefaultConfig.TV_SIZE, context));
        mPicker.setNormalTextSize(AttrHelper.fp2px(DefaultConfig.TV_SIZE, context));
        mPicker.setSelectorItemNum(7);

        mPaintLineRight = new Paint();
        mPaintLineRight.setColor(new Color(0xffe8e8e8));
        mPaintLineRight.setAntiAlias(true);
        mPaintLineRight.setStrokeWidth(1);
        mPaintLineRight.setStyle(Paint.Style.FILL_STYLE);
        mLineRightMar = AttrHelper.vp2px(15, context);

        Color themeColor = new Color(DefaultConfig.COLOR);
        mCenterRectPaint = new Paint();
        mCenterRectPaint.setColor(themeColor);
        mCenterRectPaint.setAlpha(0.1F);

        mLineRectPaint = new Paint();
        mLineRectPaint.setColor(themeColor);
    }

    @Override
    public boolean onEstimateSize(int widthSpace, int heightSpace) {
        width = EstimateSpec.getSize(widthSpace);
        height = EstimateSpec.getSize(heightSpace);
        return false;
    }

    @Override
    public void onDraw(Component component, Canvas canvas) {
        int center = getHeight() / 2;
        int offset = (int) (itemHeight / 2 * 1.2);
        canvas.drawRect(0, center - offset, width, center + offset, mCenterRectPaint);
        canvas.drawLine(0, center - offset, width, center - offset, mLineRectPaint);
        canvas.drawLine(0, center + offset, width, center + offset, mLineRectPaint);
        int x = width - 1;
        canvas.drawLine(x, mLineRightMar, x, height - mLineRightMar, mPaintLineRight);
    }

    /**
     * Adds wheel changing listener
     *
     * @param listener the listener
     */
    public void addChangingListener(OnWheelChangedListener listener) {
        changingListeners.add(listener);
    }

    /**
     * Removes wheel changing listener
     *
     * @param listener the listener
     */
    public void removeChangingListener(OnWheelChangedListener listener) {
        changingListeners.remove(listener);
    }

    /**
     * setVisibleItems
     *
     * @param count count
     */
    public void setVisibleItems(int count) {
        mPicker.setSelectorItemNum(count);
    }

    /**
     * setViewAdapter
     *
     * @param adapter adapter
     */
    public void setViewAdapter(WheelViewAdapter adapter) {
        mAdapter = adapter;
        mPicker.setMinValue(0);
        mPicker.setMaxValue(adapter.getItemCount() - 1);
        setConfig(adapter.getConfig());
    }

    /**
     * setConfig
     *
     * @param config config
     */
    public void setConfig(PickerConfig config) {
        mPicker.setNormalTextColor(new Color(config.mWheelTVNormalColor));
        mPicker.setSelectedTextColor(new Color(config.mWheelTVSelectorColor));
        mCenterRectPaint.setColor(new Color(config.mThemeColor));
        mLineRectPaint.setColor(new Color(config.mThemeColor));
        mCenterRectPaint.setAlpha(0.1F);
    }

    /**
     * setCyclic
     *
     * @param isCyclic isCyclic
     */
    public void setCyclic(boolean isCyclic) {
        mPicker.setWheelModeEnabled(isCyclic);
    }

    /**
     * Sets the current item w/o animation. Does nothing when index is wrong.
     *
     * @param index the item index
     */
    public void setCurrentItem(int index) {
        setCurrentItem(index, false);
    }

    /**
     * Sets the current item. Does nothing when index is wrong.
     *
     * @param index the item index
     * @param animated the animation flag
     */
    public void setCurrentItem(int index, boolean animated) {
        if (index <= -1) {
            return;
        }
        mPicker.setValue(index);
    }

    /**
     * Notifies changing listeners
     *
     * @param oldValue the old wheel value
     * @param newValue the new wheel value
     */
    protected void notifyChangingListeners(int oldValue, int newValue) {
        for (OnWheelChangedListener changingListener : changingListeners) {
            changingListener.onChanged(this, oldValue, newValue);
        }
    }

    /**
     * Gets current value
     *
     * @return the current value
     */
    public int getCurrentItem() {
        return mPicker.getValue();
    }

    /**
     * DataFormat
     *
     * @since 2021-07-19
     */
    private class DataFormat implements Picker.Formatter {

        @Override
        public String format(int index) {
            if (mAdapter != null) {
                return mAdapter.getItem(index);
            }
            return null;
        }
    }

    /**
     * ValueChange
     *
     * @since 2021-07-19
     */
    private class ValueChange implements Picker.ValueChangedListener {
        @Override
        public void onValueChanged(Picker picker, int oldVal, int newVal) {
            notifyChangingListeners(oldVal, newVal);
        }
    }

    /**
     * Tests if wheel is cyclic. That means before the 1st item there is shown the last one
     *
     * @return true if wheel is cyclic
     */
    public boolean isCyclic() {
        return isCyclic;
    }

}
